module(..., package.seeall)
--[[

===========================================================
Author: Osvaldo Ros (osvaldo@splosive.com)

Copyright (C) 2011 by Splosive Labs (www.splosive.com)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN

===========================================================
]]


com = require("RDX")

local physics = require("physics")
local Class = require("RDX_Class")


--[[
================================================
Objects package 

 	This library contains objects that can be used with Splosive's RDX framework.
	
	All object factories must implement a create and a destroy method. The easiest way to get started is by extending the Object template.
	It is strongly recommended that you don't modify this file and instead you create your own objects file and use the registerObjects method in your main.lua
	in order to load your own objects like this:

	com = require("RDX")

	config = com.splosive.Config
	config.registerObjects("MyObjects")

================================================
]]


--[[
	================================================
	templates package
	================================================
	]]
function buildTemplates()

	local ObjectTemplate = function(context, public, protected)
		
		super = Class.buildClass(nil, public, protected)
		
		super.public.create = function()
			com.splosive.trace("ObjectTemplate > create", "View-Object-Template")
		end
		
		-- called to let us know we've been created
		super.public.created = function()
			com.splosive.trace("ObjectTemplate > created", "View-Object-Template")
		end
		
		super.public.destroy = function()
			com.splosive.trace("ObjectTemplate > destroy", "View-Object-Template")
		end
		
		super.protected.context = context
		
		super.public.type = context.descriptor.type
		super.public.object = nil
		
		protected.dispatchEvent = function( event )
			if(public.object ~= nil)then
				event.target = public.object
				public.object:dispatchEvent( event )
			end
		end
		
		
		return super
		
	end
	
	package.ObjectTemplate = ObjectTemplate
	
	return package
	
end

templates = buildTemplates()


--[[
	================================================
	Physics package: Contains behaviors associated with phycis simulations
	================================================
	]]

function splosive()
	
	local package = {}

	
	--[[
		================================================
		Image 
		================================================
	]]

	local Image = function(context)
	
		local public = {}
		local protected = {}
		--local layoutManager = com.splosive.LayoutManager
		
		local super = templates.ObjectTemplate(context, public, protected)
		-- this is what makes the whole thing work, methods access 'this' which points to the sub class 'private', if an implementation is not found there, then
		-- it will go up to the base class
		local this = protected
		-- same goes for the public, we should always access public through api, this way it will look in the subclass first and then the super class
		local api = public
		
		
		public.create = function()
			super.public.create()
			com.splosive.trace("Image > create", "View-Object-Image")
			
			if(this.context.descriptor.imageWidth ~= nil and this.context.descriptor.imageHeight ~= nil)then
				api.object = display.newImageRect( this.context.descriptor.asset, this.context.descriptor.imageWidth, this.context.descriptor.imageHeight )
			else
				api.object = display.newImage( this.context.descriptor.asset )
			end				
			
			-- This makes layout easier but fucks up the physics ( instead we are adjusting the layout knowing that the registration point is in the center )
			--object:setReferencePoint( display.TopLeftReferencePoint ) 
			
			local bodyType = this.context.descriptor.bodyType
			if(bodyType == nil) then
				bodyType = "static"
			end
			
			--layoutManager.doLayout(api.object, this.context.descriptor, this.context.parent)
			
			if (this.context.currentView.physicsEnabled and bodyType ~= "none") then
				physics.addBody( api.object, bodyType, { density=this.context.descriptor.density or 3.0, friction=this.context.descriptor.friction or 0.5, bounce=this.context.descriptor.bounce or 0.3 } )
			end
			
			if(this.context.descriptor.isSensor ~= nil)then
				api.object.isSensor = this.context.descriptor.isSensor
			end
			
			return api
				
		end
		
		public.destroy = function()
			com.splosive.trace("Image > destroy", "View-Object-Image")
		end
		
		return api
		
	end
	
	--[[
		================================================
		Button 
		================================================
	]]

	local Button = function(context)
	
		local public = {}
		local protected = {}
		--local layoutManager = com.splosive.LayoutManager
		
		local super = templates.ObjectTemplate(context, public, protected)
		-- this is what makes the whole thing work, methods access 'this' which points to the sub class 'private', if an implementation is not found there, then
		-- it will go up to the base class
		local this = protected
		-- same goes for the public, we should always access public through api, this way it will look in the subclass first and then the super class
		local api = public
		
		this.view = nil
		
		public.create = function()
			super.public.create()
			com.splosive.trace("Button > create", "View-Object-Button")
			
			if(this.context.descriptor.upAsset == nil)then
				if(this.context.descriptor.asset == nil)then
					error("Plase specify at least upAsset or asset for Button object")
				else
					this.context.descriptor.upAsset = this.context.descriptor.asset
				end
			end
			
			if(this.context.descriptor.downAsset == nil)then
				this.context.descriptor.downAsset = this.context.descriptor.upAsset
			end
			
			
			local viewFile = require("RDX_Button")
			this.childView = viewFile.getView(this.context)
			this.childView.parentView = this.context.currentView
			
			local object = this.childView.mainGroup	
			-- This makes layout easier but fucks up the physics ( instead we are adjusting the layout knowing that the registration point is in the center )
			--object:setReferencePoint( display.TopLeftReferencePoint ) 
			
			local bodyType = this.context.descriptor.bodyType
			if(bodyType == nil) then
				bodyType = "none"
			end
			
			--layoutManager.doLayout(api.object, this.context.descriptor, this.context.parent)
			
			if (this.context.currentView.physicsEnabled and bodyType ~= "none") then
				physics.addBody( object, bodyType, { density=this.context.descriptor.density or 3.0, friction=this.context.descriptor.friction or 0.5, bounce=this.context.descriptor.bounce or 0.3 } )
			end
			
			this.childView.object = object
			this.childView.destroy = public.destroy
			this.childView.created = public.created
			
			this.childView.type = public.type
			
			return this.childView
			
				
		end
		
		public.destroy = function()
			com.splosive.trace("Button > destroy", "View-Object-Button")
			this.childView.clean()
		end
		
		return api
		
	end
	
	--[[
		================================================
		MovingImage 
		================================================
	]]

	local MovingImage = function(context)
	
		local public = {}
		local protected = {}
		--local layoutManager = com.splosive.LayoutManager
		
		local super = templates.ObjectTemplate(context, public, protected)
		-- this is what makes the whole thing work, methods access 'this' which points to the sub class 'private', if an implementation is not found there, then
		-- it will go up to the base class
		local this = protected
		-- same goes for the public, we should always access public through api, this way it will look in the subclass first and then the super class
		local api = public
		
		protected.minX = nil
		protected.minY = nil
		protected.maxX = nil
		protected.maxY = nil
		
		protected.horizontalDirection = 0
		protected.verticalDirection = 0
		protected.velocityChanged = false
		protected.lastTime = 0
		
		protected.passengers = {}
		
		public.create = function()
			super.public.create()
			com.splosive.trace("MovingImage > create", "View-Object-MovingImage")
			
			if(this.context.descriptor.imageWidth ~= nil and this.context.descriptor.imageHeight ~= nil)then
				api.object = display.newImageRect( this.context.descriptor.asset, this.context.descriptor.imageWidth, this.context.descriptor.imageHeight )
			else
				api.object = display.newImage( this.context.descriptor.asset )
			end				
			
			local bodyType = this.context.descriptor.bodyType
			if(bodyType == nil) then
				bodyType = "kinematic"
			end
			
			if (this.context.currentView.physicsEnabled and bodyType ~= "none") then
				physics.addBody( api.object, bodyType, { density=this.context.descriptor.density or 3.0, friction=this.context.descriptor.friction or 0.5, bounce=this.context.descriptor.bounce or 0.3 } )
			end
			
			if(this.context.descriptor.isSensor ~= nil)then
				api.object.isSensor = this.context.descriptor.isSensor
			end
			
			this.passengers = {}
			
			return api
				
		end
		
		public.created = function()
			com.splosive.trace("MovingImage > created, bodyType = " .. api.object.bodyType, "View-Object-MovingImage")
			
			if(this.context.descriptor.rangeX == nil)then
				this.context.descriptor.rangeX = 0
			end
			
			if(this.context.descriptor.rangeY == nil)then
				this.context.descriptor.rangeY = 0
			end
			
			if(this.context.descriptor.rangeX > 0)then
				this.minX = api.object.x
				this.maxX = this.minX + this.context.descriptor.rangeX
				this.horizontalDirection = 1
			elseif(this.context.descriptor.rangeX < 0)then
				this.maxX = api.object.x
				this.minX = this.maxX + this.context.descriptor.rangeX
				this.horizontalDirection = -1
			else
				this.horizontalDirection = 0
			end
			
			if(this.context.descriptor.rangeY > 0)then
				this.minY = api.object.y
				this.maxY = this.minY + this.context.descriptor.rangeY
				this.verticalDirection = 1
			elseif(this.context.descriptor.rangeY < 0)then
				this.maxY = api.object.y
				this.minY = this.maxY + this.context.descriptor.rangeY
				this.verticalDirection = -1
			else
				this.verticalDirection = 0
			end
			
			this.velocityChanged = true
			this.lastTime = system.getTimer()
			
			api.object:addEventListener("collision", this.objectCollision)
			Runtime:addEventListener("enterFrame", this.onEnterFrame)
					
		end
		
		protected.objectCollision = function(event)
			if(event.phase == "began") then
				this.passengers[#this.passengers + 1] = event.other
			elseif(event.phase == "ended") then
				for k,passenger in ipairs(this.passengers) do
					if(passenger == event.other)then
						this.passengers[k] = nil
					end
				end
			end
		end
		
		protected.onEnterFrame = function()
			com.splosive.trace("MovingImage > applyForce > ", "View-Object-MovingImage")
			
			local linearVelocityX = 30 * this.horizontalDirection
			local linearVelocityY = 30 * this.verticalDirection
			
			--[[
			]]
			if(this.velocityChanged)then
				api.object:setLinearVelocity( linearVelocityX, linearVelocityY )
				this.velocityChanged = false
			end
			--[[
			local timeElapsed = system.getTimer() - this.lastTime
			if(linearVelocityX ~= 0)then
				api.object.x = api.object.x + ( linearVelocityX * (timeElapsed/1000) )
			end
			if(linearVelocityY ~= 0)then
				api.object.y = api.object.y + ( linearVelocityY * (timeElapsed/1000) )
			end
			this.lastTime = system.getTimer()
			]]
			
			for k,passenger in ipairs(this.passengers) do
				if(passenger ~= nil)then
					local velX, velY = passenger:getLinearVelocity()
					com.splosive.trace("MovingImage > applyForce > (" .. velX .. ", ".. velY ..")", "View-Object-MovingImage")
					passenger:setLinearVelocity(velX,0)
				end
			end
			
			
			if(this.verticalDirection == 1)then
				if(api.object.y >= this.maxY)then
					this.verticalDirection = -1
					this.velocityChanged = true
				end
			elseif(this.verticalDirection == -1)then
				if(api.object.y <= this.minY)then
					this.verticalDirection = 1
					this.velocityChanged = true
				end
			end
			
			if(this.horizontalDirection == 1)then
				if(api.object.x >= this.maxX)then
					this.horizontalDirection = -1
					this.velocityChanged = true
				end
			elseif(this.horizontalDirection == -1)then
				if(api.object.x <= this.minX)then
					this.horizontalDirection = 1
					this.velocityChanged = true
				end
			end
			
		end
		
		protected.transitionEnd = function()
			com.splosive.trace("MovingImage > transitionEnd > " .. startX, "View-Object-MovingImage")
			if(this.context.descriptor.loop == true)then
				local transitionProperties = {transition=easing.Out, time=this.context.descriptor.duration, onComplete=this.transitionEnd}
				
				if(this.context.descriptor.toX ~= nil) then
					if(api.object.x == this.context.descriptor.toX)then
						transitionProperties.x = startX
					else
						transitionProperties.x = this.context.descriptor.toX
					end
				end
				if(this.context.descriptor.toY ~= nil) then 
					if(api.object.y == this.context.descriptor.toY)then
						transitionProperties.y = startY
					else
						transitionProperties.y = this.context.descriptor.toY
					end
				end
					
				transition.to( api.object, transitionProperties )
				
			end
		end
		
		public.destroy = function()
			com.splosive.trace("MovingImage > destroy", "View-Object-MovingImage")
			Runtime:removeEventListener("enterFrame", this.onEnterFrame)	
		end
		
		return api
		
	end
	
	--[[
		================================================
		View 
		================================================
	]]

	local View = function(context)
	
		local public = {}
		local protected = {}
		--local layoutManager = com.splosive.LayoutManager
		
		local super = templates.ObjectTemplate(context, public, protected)
		-- this is what makes the whole thing work, methods access 'this' which points to the sub class 'private', if an implementation is not found there, then
		-- it will go up to the base class
		local this = protected
		-- same goes for the public, we should always access public through api, this way it will look in the subclass first and then the super class
		local api = public
		
		this.view = nil
		
		public.create = function()
			super.public.create()
			com.splosive.trace("View > create", "View-Object-View")
			
			local viewFile = require(this.context.descriptor.source)
			this.childView = viewFile.getView(this.context)
			this.childView.parentView = this.context.currentView
			
			local object = this.childView.mainGroup	
			-- This makes layout easier but fucks up the physics ( instead we are adjusting the layout knowing that the registration point is in the center )
			--object:setReferencePoint( display.TopLeftReferencePoint ) 
			
			local bodyType = this.context.descriptor.bodyType
			if(bodyType == nil) then
				bodyType = "none"
			end
			
			--layoutManager.doLayout(api.object, this.context.descriptor, this.context.parent)
			
			if (this.context.currentView.physicsEnabled and bodyType ~= "none") then
				physics.addBody( object, bodyType, { density=this.context.descriptor.density or 3.0, friction=this.context.descriptor.friction or 0.5, bounce=this.context.descriptor.bounce or 0.3 } )
			end
			
			this.childView.object = object
			this.childView.destroy = public.destroy
			this.childView.created = public.created
			
			this.childView.type = public.type
			
			return this.childView
				
		end
		
		public.destroy = function()
			com.splosive.trace("View > destroy", "View-Object-View")
			this.childView.clean()
		end
		
		return api
		
	end
	
	--[[
		================================================
		Rectangle 
		================================================
	]]

	local Rectangle = function(context)
	
		local public = {}
		local protected = {}
		--local layoutManager = com.splosive.LayoutManager
		local NumberUtils = com.splosive.NumberUtils
		
		local super = templates.ObjectTemplate(context, public, protected)
		-- this is what makes the whole thing work, methods access 'this' which points to the sub class 'private', if an implementation is not found there, then
		-- it will go up to the base class
		local this = protected
		-- same goes for the public, we should always access public through api, this way it will look in the subclass first and then the super class
		local api = public
		
		this.strokeColor = "000000"
		this.fillColor = "666666"
		this.stroke = 1
		
		public.create = function()
			super.public.create()
			com.splosive.trace("Rectangle > create", "View-Object-Rectangle")
			
			this.fillColor = this.context.descriptor.fillColor or "666666"
			this.strokeColor = this.context.descriptor.strokeColor or "000000"
			this.stroke = this.context.descriptor.stroke or 1
			--this.context.descriptor.zeroBased = true
			
			api.object = display.newRect( 0, 0,  this.context.descriptor.width, this.context.descriptor.height)
			api.object.strokeWidth = this.stroke
			
			local r,g,b = NumberUtils.hexToRGB(this.fillColor)
			api.object:setFillColor(r, g, b)
			
			r,g,b = NumberUtils.hexToRGB(this.strokeColor)
			api.object:setStrokeColor(r, g, b)
			
				
			-- This makes layout easier but fucks up the physics ( instead we are adjusting the layout knowing that the registration point is in the center )
			--object:setReferencePoint( display.TopLeftReferencePoint ) 
			
			local bodyType = this.context.descriptor.bodyType
			if(bodyType == nil) then
				bodyType = "static"
			end
			
			--layoutManager.doLayout(api.object, this.context.descriptor, this.context.parent)
			
			if (this.context.currentView.physicsEnabled and bodyType ~= "none") then
				physics.addBody( api.object, bodyType, { density=this.context.descriptor.density or 3.0, friction=this.context.descriptor.friction or 0.5, bounce=this.context.descriptor.bounce or 0.3 } )
			end
			
			return api
				
		end
		
		public.destroy = function()
			com.splosive.trace("Rectangle > destroy", "View-Object-Rectangle")
		end
		
		return api
		
	end
	
	
	--[[
		================================================
		Text 
		================================================
	]]

	local Text = function(context)
	
		local public = {}
		local protected = {}
		--local layoutManager = com.splosive.LayoutManager
		local NumberUtils = com.splosive.NumberUtils
		
		local super = templates.ObjectTemplate(context, public, protected)
		-- this is what makes the whole thing work, methods access 'this' which points to the sub class 'private', if an implementation is not found there, then
		-- it will go up to the base class
		local this = protected
		-- same goes for the public, we should always access public through api, this way it will look in the subclass first and then the super class
		local api = public
		
		this.font = native.systemFont
		this.size = 12
		this.color = "000000"
		
		public.create = function()
			super.public.create()
			com.splosive.trace("Text > create", "View-Object-Text")
			
			this.font = this.context.descriptor.font --or native.systemFont
			this.size = this.context.descriptor.size or 12
			this.context.descriptor.x = this.context.descriptor.x or 0
			this.context.descriptor.y = this.context.descriptor.y or 0
			this.color = this.context.descriptor.color or "000000"
			--this.context.descriptor.zeroBased = true
			
			api.object = display.newText( this.context.parent, this.context.descriptor.text, this.context.descriptor.x , this.context.descriptor.y,  this.font, this.size)
			local r,g,b = NumberUtils.hexToRGB(this.color)
			api.object:setTextColor(r, g, b)
			
			api.object.text = this.context.descriptor.text
			api.object:setReferencePoint(display.CenterReferencePoint);
			api.object.x = this.context.descriptor.x
			api.object.y = this.context.descriptor.y
				
			-- This makes layout easier but fucks up the physics ( instead we are adjusting the layout knowing that the registration point is in the center )
			--api.object:setReferencePoint( display.TopLeftReferencePoint ) 
			
			local bodyType = this.context.descriptor.bodyType
			if(bodyType == nil) then
				bodyType = "none"
			end
			
			--layoutManager.doLayout(api.object, this.context.descriptor, this.context.parent)
			
			com.splosive.trace("Text has been layed out", "View-Object-Text")
			
			if (this.context.currentView.physicsEnabled and bodyType ~= "none") then
				physics.addBody( api.object, bodyType, { density=this.context.descriptor.density or 3.0, friction=this.context.descriptor.friction or 0.5, bounce=this.context.descriptor.bounce or 0.3 } )
			end
			
			return api
				
		end
		
		public.destroy = function()
			com.splosive.trace("Text > destroy", "View-Object-Text")
		end
		
		return api
		
	end
	
	--[[
		================================================
		Sprite 
		================================================
	]]

	local SpriteSet = function(context)
	
		local public = {}
		local protected = {}
		--local layoutManager = com.splosive.LayoutManager
		
		local super = templates.ObjectTemplate(context, public, protected)
		-- this is what makes the whole thing work, methods access 'this' which points to the sub class 'private', if an implementation is not found there, then
		-- it will go up to the base class
		local this = protected
		-- same goes for the public, we should always access public through api, this way it will look in the subclass first and then the super class
		local api = public
		
		
		public.create = function()
			super.public.create()
			com.splosive.trace("Sprite > create", "View-Object-SpriteSet")
			
			-- notice how we don't set object to anything here, createSprite will take care of adding the sprites to the group
			local sheet = sprite.newSpriteSheet( this.context.descriptor.asset, this.context.descriptor.frameWidth, this.context.descriptor.frameHeight )
			
			local startFrame = this.context.descriptor.startFrame or 1
			local autoPlay = this.context.descriptor.autoPlay or true
			local defaultSequence = this.context.descriptor.defaultSequence
			local frameCount = this.context.descriptor.frameCount or sheet.frameCount
			
			local spriteSet = sprite.newSpriteSet(sheet, startFrame, frameCount)
			
			
			if(this.context.descriptor.sprites ~= nil)then
				for k,spriteDescriptor in ipairs(this.context.descriptor.sprites) do 
						
					local startFrame = spriteDescriptor.startFrame or 1
					local frameCount = spriteDescriptor.frameCount or (sheet.frameCount - 1)
					
					local duration = spriteDescriptor.duration or 1000
					local loop = spriteDescriptor.loop or 0
					
					sprite.add( spriteSet, spriteDescriptor.name, startFrame, frameCount, duration, loop )
					
					if(defaultSequence == nil)then
						defaultSequence = spriteDescriptor.name
					end
						
				end
			else
				error("Please include at least one sprite for spriteSet")
			end
			
			
			api.object = sprite.newSprite( spriteSet )
			-- This makes layout easier but fucks up the physics ( instead we are adjusting the layout knowing that the registration point is in the center )
			--object:setReferencePoint( display.TopLeftReferencePoint ) 
			
			local bodyType = this.context.descriptor.bodyType
			if(bodyType == nil) then
				bodyType = "static"
			end
			
			--layoutManager.doLayout(api.object, this.context.descriptor, this.context.parent)
			
			api.object:prepare(defaultSequence)
			if(autoPlay) then 
				api.object:play() 
			end
			
			
			if (this.context.currentView.physicsEnabled and bodyType ~= "none") then
				physics.addBody( api.object, bodyType, { density=this.context.descriptor.density or 3.0, friction=this.context.descriptor.friction or 0.5, bounce=this.context.descriptor.bounce or 0.3 } )
			end
			
						
			if(this.context.descriptor.isFixedRotation ~= nil) then
				api.object.isFixedRotation = this.context.descriptor.isFixedRotation
			end
			
			return api
				
		end
		
		public.destroy = function()
			com.splosive.trace("Image > destroy", "View-Object-SpriteSet")
		end
		
		return api
		
	end
	
	--[[
		================================================
		Conveyor 
		================================================
	]]

	local Conveyor = function(context)
	
		local public = {}
		local protected = {}
		--local layoutManager = com.splosive.LayoutManager
		local SpriteSet = package.objects.SpriteSet
		
		local super = templates.ObjectTemplate(context, public, protected)
		-- this is what makes the whole thing work, methods access 'this' which points to the sub class 'private', if an implementation is not found there, then
		-- it will go up to the base class
		local this = protected
		-- same goes for the public, we should always access public through api, this way it will look in the subclass first and then the super class
		local api = public
		
		protected.passenger = nil
		
		public.create = function()
			super.public.create()
			com.splosive.trace("Conveyor > create", "View-Object-Conveyor")
			
			local imageFactory = SpriteSet(this.context)
			
			api.object = imageFactory.create().object
			
			--com.splosive.trace("object id = " .. api.object, "View-Object")
			
			api.object:addEventListener( "collision", this.objectCollision )
			
			return api
			
				
		end
		
		protected.objectCollision = function(event)
			if(event.phase == "began") then
				protected.passenger = event.other
				Runtime:addEventListener( "enterFrame", this.onEnterFrame )
			elseif(event.phase == "ended") then
				Runtime:removeEventListener( "enterFrame", this.onEnterFrame )
			end
		end
		
		protected.onEnterFrame = function( event )
		
			if(com.splosive.PhysicsState.physicsRunning == false)then
				return
			end
			--local tDelta = event.time - this.previousInstant
			--this.previousInstant = event.time
			
			--protected.passenger.x = protected.passenger.x + 5
			--com.splosive.trace("applying force", "View-Object")
			protected.passenger:applyForce(this.context.descriptor.force, 0, protected.passenger.x, protected.passenger.y )
			 
		end
		
		public.destroy = function()
			com.splosive.trace("Image > destroy", "View-Object-Conveyor")
			Runtime:removeEventListener( "enterFrame", this.onEnterFrame )
			api.object:removeEventListener( "collision", this.objectCollision )
		end
		
		return api
		
	end
	
	--[[
		================================================
		Trampoline 
		================================================
	]]

	local Trampoline = function(context)
	
		local public = {}
		local protected = {}
		--local layoutManager = com.splosive.LayoutManager
		local Image = package.objects.Image
		
		local super = templates.ObjectTemplate(context, public, protected)
		-- this is what makes the whole thing work, methods access 'this' which points to the sub class 'private', if an implementation is not found there, then
		-- it will go up to the base class
		local this = protected
		-- same goes for the public, we should always access public through api, this way it will look in the subclass first and then the super class
		local api = public
		
		public.events = {
			onBounce="onBounce"
		}
		
		protected.passenger = nil
		protected.entryForceX = 0
		protected.entryForceY = 0
		protected.soundObj = nil
		
		public.create = function()
			super.public.create()
			com.splosive.trace("Trampoline > create", "View-Object-Trampoline")
			
			local imageFactory = Image(this.context)
			api.object = imageFactory.create().object
			api.object:addEventListener( "collision", this.objectCollision )
			--api.object:addEventListener( "postCollision", this.objectPostCollision )
			
			if(this.context.descriptor.sound)then
				this.soundObj = audio.loadSound( this.context.descriptor.sound )
			end
			
			return api
			
		end
		
		protected.objectCollision = function(event)
			
			if(event.phase == "began") then
				local vx, vy = event.other:getLinearVelocity()
				com.splosive.trace("Trampoline > "..event.phase.." > vx = " .. vx .. ", vy = " .. vy,  "View-Object-Trampoline")
				
				local forceFactor = 3
				if(this.context.descriptor.elasticity == "soft")then
					forceFactor = 3
				elseif(this.context.descriptor.elasticity == "regular")then
					forceFactor = 2
				elseif(this.context.descriptor.elasticity == "hard")then
					forceFactor = 1
				end
				
				
				protected.passenger = event.other
				protected.entryForceX = vx/3
				protected.entryForceY = vy/3
				Runtime:addEventListener( "enterFrame", this.onEnterFrame )
			elseif(event.phase == "ended") then
				if(this.soundObj ~= nil)then
					audio.play( this.soundObj )
				end
				Runtime:removeEventListener( "enterFrame", this.onEnterFrame )
			end
		end
		
		protected.onEnterFrame = function( event )
			com.splosive.trace("Trampoline > apply force x = " .. protected.entryForceX .. ", y = 0 ",  "View-Object-Trampoline")
			protected.passenger:applyLinearImpulse( protected.entryForceX, 0, protected.passenger.x, protected.passenger.y )
			this.dispatchEvent({name=public.events.onBounce})
		end
		
		
		public.destroy = function()
			com.splosive.trace("Trampoline > destroy", "View-Object-Trampoline")
			api.object:removeEventListener( "collision", this.objectCollision )
		end
		
		return api
		
	end
	
	--[[
		================================================
		Teeter 
		================================================
	]]

	local Teeter = function(context)
	
		local public = {}
		local protected = {}
		local layoutManager = com.splosive.LayoutManager
		
		local super = templates.ObjectTemplate(context, public, protected)
		-- this is what makes the whole thing work, methods access 'this' which points to the sub class 'private', if an implementation is not found there, then
		-- it will go up to the base class
		local this = protected
		-- same goes for the public, we should always access public through api, this way it will look in the subclass first and then the super class
		local api = public
		
		protected.base = nil
		protected.arm = nil
		
		public.create = function()
			super.public.create()
			com.splosive.trace("Teeter > create", "View-Object-Teeter")
			
			--api.object = display.newGroup()
			
			this.base = display.newImage( this.context.descriptor.base )
			this.arm = display.newImage( this.context.descriptor.arm )
			this.base.id = "Teeter_base"
				
			--api.object:insert(this.base)
			--api.object:insert(this.arm)
			
			this.context.parent:insert(this.base)
			this.context.parent:insert(this.arm)
			
			-- This makes layout easier but fucks up the physics ( instead we are adjusting the layout knowing that the registration point is in the center )
			--object:setReferencePoint( display.TopLeftReferencePoint ) 
			
			layoutManager.doLayout(this.base, this.context.descriptor, this.context.parent, this.context.currentView.coordinatePolicy)
			
			this.arm.y = this.base.y - this.base.height
			this.arm.x = this.base.x
			
			--api.object = this.base
			
			
			--[[
			]]
			if (this.context.currentView.physicsEnabled) then
				physics.addBody( this.base, "static", { density=this.context.descriptor.density or 3.0, friction=this.context.descriptor.friction or 0.5, bounce=this.context.descriptor.bounce or 0.3 } )
			end
			
			
			if (this.context.currentView.physicsEnabled) then
				physics.addBody( this.arm, "dynamic", { density=this.context.descriptor.density or 3.0, friction=this.context.descriptor.friction or 0.5, bounce=this.context.descriptor.bounce or 0.3 } )
			end
			
			
			local catapultJoint = physics.newJoint( "pivot", this.base, this.arm, this.base.x, this.base.y - this.base.height/2)
			
			return api
				
		end
		
		public.destroy = function()
			com.splosive.trace("Teeter > destroy", "View-Object-Teeter")
			this.arm:removeSelf()
			this.base:removeSelf()
			this.arm = nil
			this.base = nil
		end
		
		return api
		
	end
	
	local objects = {}
	
	objects.View = View
	objects.Text = Text
	objects.Rectangle = Rectangle
	objects.Image = Image
	objects.Button = Button
	objects.MovingImage = MovingImage
	objects.SpriteSet = SpriteSet
	objects.Conveyor = Conveyor
	objects.Trampoline = Trampoline
	objects.Teeter = Teeter
	
	package.objects = objects
	
	
	return package


end
	
